package com.chujian.framework.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.OrderComparator;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.ArrayList;
import java.util.List;

/**
 * Spring 相关
 * 实现 BeanPostProcessor => 提高当前类的加载优先级
 */
@Slf4j
public class Spring implements ApplicationContextAware, BeanPostProcessor {

    public static final String SPRING_US_BEAN_NAME = "spring";

    public static ApplicationContext ctx = null;

    public Object getBean(String name) {
        return Spring.ctx.getBean(name);
    }

    /**
     * 获取单个bean
     *
     * @param type type
     * @param <T>  T
     * @return T
     */
    public static <T> T getBean(Class<T> type) {
        if (null == ctx) {
            log.error("spring ctx is null");
            return null;
        }
        return getBean(ctx, type);
    }

    public static <T> T getBean(ApplicationContext ctx, Class<T> type) {
        try {
            return ctx.getBean(type);
        } catch (NoSuchBeanDefinitionException e) {
            log.error("spring ctx hasn't a bean of " + type.getName());
            return null;
        }
    }

    /**
     * 获取bean列表
     *
     * @param type type
     * @param <T>  T
     * @return List<T>
     */
    public static <T> List<T> getBeans(Class<T> type) {
        if (null == ctx) {
            log.error("spring ctx is null");
            return null;
        }
        return new ArrayList<>(ctx.getBeansOfType(type).values());
    }

    /**
     * 获取RequestMapping注解信息，
     *
     * @param clazzStr
     * @return
     */
    public static String getSpringRequestMapping(String clazzStr) {
        try {
            Class<?> clazz = Class.forName(clazzStr);
            return getSpringRequestMapping(clazz);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    public static String getSpringRequestMapping(Class<?> clazz) {
        RequestMapping requestMapping = clazz.getAnnotation(RequestMapping.class);
        String[] value = requestMapping.value();
        if (value.length > 0) {
            return value[0];
        }
        return null;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        Spring.ctx = applicationContext;
    }

    /**
     * SpringBean 排序
     *
     * @param list list
     * @param <T>  T
     */
    public static <T> void sortBeans(List<T> list) {
        list.sort(OrderComparator.INSTANCE);
    }

}
